using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
using System.IO;

namespace ConsolePlayer
{
	public class CommandLrc : ICommand, IConnection
	{

		private IPlayerCore core = null;
		private System.Timers.Timer timer = null;
		private string lrcFile = string.Empty;
		private SortedList<TimeSpan, string> lrc = new SortedList<TimeSpan, string>();
		int curLeft = 0;
		int curTop = 0;

		private void timer_Elapsed(object sender, ElapsedEventArgs e)
		{
			Console.Clear();


			FileInfo info = new FileInfo(core.CurrentFile);

			long duration_second = core.Duration/1000;
			long current_second = core.CurrentPosition/1000;

			TimeSpan duration = new TimeSpan(0,0,(int)duration_second);
			TimeSpan current = new TimeSpan(0,0,(int)current_second);
			Console.CursorLeft = 0;
			Console.CursorTop = 0;
			Console.WriteLine("[{0}]\t{1}:{2}:{3} / {4}:{5}:{6}\t[{7}:{8}:{9}]\n\n",
				info.Name, 
				current.Hours, current.Minutes, current.Seconds,
				duration.Hours, duration.Minutes, duration.Seconds,
				DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
			PrintLrcLine(current, Console.WindowHeight-5);
		}

		private void PrintLrcLine(TimeSpan currentTime, int depth)
		{
			if (depth % 2 == 0) depth += 1;
			int index = 0;
			for( index = 0 ; index < lrc.Count; index++ )
			{
				TimeSpan span = lrc.Keys[index];
				if (span > currentTime)
					break;
			}
			if (index == lrc.Count) return;
			index--;
			if (index < 0) return;
			int current = index;

			for( index = 0 ; index < depth; index++ )
			{
				int offset = index - (depth / 2 );
				int needed = current + offset;
				if (needed >= lrc.Count || needed < 0)
				{
					Console.WriteLine("");
				}
				else
				{
					ConsoleColor old = Console.ForegroundColor;
					if (index == (depth / 2))
						Console.ForegroundColor = ConsoleColor.DarkGreen;
					Console.CursorLeft = curLeft;
					Console.WriteLine(lrc.Values[needed]);
					Console.ForegroundColor = old;
				}
			}
		}

		private List<string> GetStrings(string s)
		{
			List<string> ret = new List<string>();
			string left, right;
			int index = s.LastIndexOf(']');
			if (index == -1) return ret;
			left = s.Substring(0, index);
			right = s.Substring(index + 1, s.Length - index - 1);
			char[] split = { '[', ']' };
			string[] ss = left.Split(split);
			foreach (string part in ss)
			{
				if (!string.IsNullOrEmpty(part))
					ret.Add(part);
			}
			ret.Add(right);
			return ret;
		}

		private List<string> GetTimeStrings(string s)
		{
			List<string> ret = new List<string>();
			char[] split = { '.', ':' };
			string[] ss = s.Split(split);
			foreach (string part in ss)
			{
				if (!string.IsNullOrEmpty(part))
					ret.Add(part);
			}
			return ret;
		}

		#region ICommand Members

		public void Action()
		{
			//no addition command
		}

		#endregion

		#region IConnection Members

		public void Connect(IPlayerCore core)
		{
			this.core = core;

			

			Console.CursorVisible = false;
			curLeft = 10;
			curTop = 0;

			timer = new Timer();
			timer.Interval = 500;
			timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);

			lrc.Clear();
			string fileName = core.CurrentFile;
			FileInfo info = new FileInfo(fileName);
			lrcFile = fileName.Replace(info.Extension, ".lrc");
			if( File.Exists(lrcFile) )
			{
				FileStream stream = new FileStream(lrcFile, FileMode.Open);
				BinaryReader breader = new BinaryReader(stream);
				byte[] buffer = new byte[stream.Length + 1];
				breader.Read(buffer, 0, (int)stream.Length);
				stream.Close();
				string bufferString = Encoding.Default.GetString(buffer);
				StringReader reader = new StringReader(bufferString);
				//lrcEncoding = reader.CurrentEncoding;
				string line;
				while( !string.IsNullOrEmpty(line = reader.ReadLine()) )
				{

					//line = Encoding.Unicode.GetString(lrcEncoding.GetBytes(line));
					if (line.Contains("[ti") || line.Contains("[ar") ||
						line.Contains("[al") || line.Contains("[by") ||
						line.Contains("[offset") )
						continue;
					List<string> infos = GetStrings(line);
					if (infos.Count == 0) continue;
					string val = infos[infos.Count - 1];
					for (int index = 0; index < infos.Count - 1; index++)
					{
						string timeVal = infos[index];
						List<string> times = GetTimeStrings(timeVal);
						int minute = Int32.Parse(times[0]);
						int second = Int32.Parse(times[1]);
						TimeSpan span = new TimeSpan(0, minute, second);
						if (lrc.ContainsKey(span))
							lrc[span] = val;
						else
							lrc.Add(span, val);
					}
				}


			}
			timer.Start();

		}



		public void Disconnect()
		{
			Console.Clear();
			timer.Stop();
			timer.Close();
			this.core = null;

		}

		#endregion
	}
	public class Lrc : IExtension
	{
		#region IExtension Members

		public object ParseCommandLine(string[] args)
		{
			bool needLrc = false;
			foreach (string s in args)
			{
				string upper = s.ToUpper();
				if (upper == "-LRC")
					needLrc = true;
			}
			if (needLrc)
				return new CommandLrc();
			else
				return null;
		}

		#endregion
	}

}
